import re


#临时t_判断b
#args-arg ls-it
class trueTableProcess:
    ptn = [
        re.compile(  #0
            r'(\(((\(((\w|!\w)\*)+(\w|!\w)\)|(\w|!\w))\+)*(\(((\w|!\w)\*)+(\w|!\w)\)|(\w|!\w))\)'
            r'|\(((\w|!\w)\*)+(\w|!\w)\)'
            r'|(\w|!\w))\-'
            r'(\(((\(((\w|!\w)\*)+(\w|!\w)\)|(\w|!\w))\+)*(\(((\w|!\w)\*)+(\w|!\w)\)|(\w|!\w))\)'
            r'|\(((\w|!\w)\*)+(\w|!\w)\)'
            r'|(\w|!\w))')  #(a+(a*b)+c),(a*b),a
        ,
        re.compile(  #1
            r'(\(((\(((\w|!\w)\*)+(\w|!\w)\)|(\w|!\w))\+)*(\(((\w|!\w)\*)+(\w|!\w)\)|(\w|!\w))\)'
            r'|\(((\w|!\w)\*)+(\w|!\w)\)'
            r'|(\w|!\w))\='
            r'(\(((\(((\w|!\w)\*)+(\w|!\w)\)|(\w|!\w))\+)*(\(((\w|!\w)\*)+(\w|!\w)\)|(\w|!\w))\)'
            r'|\(((\w|!\w)\*)+(\w|!\w)\)'
            r'|(\w|!\w))')  #(a+(a*b)+c),(a*b),a
        ,
        re.compile(  #2
            r'(\+\(((\(((\w|!\w)\*)+(\w|!\w)\)|(\w|!\w))\+)*(\(((\w|!\w)\*)+(\w|!\w)\)|(\w|!\w))\))|'
            r'(\(((\(((\w|!\w)\*)+(\w|!\w)\)|(\w|!\w))\+)*(\(((\w|!\w)\*)+(\w|!\w)\)|(\w|!\w))\)\+)'
        ),  #+(a+b)+
        re.compile(
            r'\*\(((\w|!\w)\*)*(\w|!\w)\)|\(((\w|!\w)\*)*(\w|!\w)\)\*'  #3
        ),  #*(a*b)*
        re.compile(r'\((\w|!\w)\)'),  #4
        re.compile(r'(\+|\*)\(\)|\(\)(\+|\*)'),  #5
        re.compile(r'\*\*|\+\+'),  #6
        re.compile(r'(^(\+|\*).*)|(.*(\+|\*)$)'),  #7
        re.compile(r'\!\(((\w|!\w)\*)*(\w|!\w)\)'),  #8
    ]
    test = False

    def __init__(self, how: bool = True, test: bool = False) -> None:
        self.how = how
        self.test = test

    def process(self, root, node):
        t = node.item
        node.setItem(self.__rSC(node.item))
        if self.how and t != node.item: print(root)
        t = node.item
        node.setItem(self.__rDC(node.item))
        if self.how and t != node.item: print(root)
        t = node.item
        node.setItem(self.simplifiy(node.item))
        if self.how and t != node.item: print(root)

    def judge(self, args):
        args = list(args)
        argls = set()
        for i, ch in enumerate(args):
            if 'a' <= ch <= 'z'or'A' <= ch <= 'Z' or ch == '0':
                argls.add(ch)
                args[i] = '1'
        while True:
            l = len(args)
            args = ''.join(args).replace('!1', '1')
            args = args.replace('(1)', '1')
            for it in re.finditer(r'1(\+|\*|-|=)1', args):
                args = args.replace(it.group(), '1')
            if len(args) == l: break
        if args != '1': return False
        else: return sorted(list(argls))

    def finPar(self, args, argls):  #整理范式 finishingParadigm
        if self.test: print('fp_1: ', args)
        if len(argls) < 2: return args
        b = self.__partition(args, '+')
        if b: args = b
        else: return args
        if self.test: print('fp_2: ', args)
        wfa = []  #wait for add
        for arg in args:
            uargls = [(it, '!' + it) for it in argls if it not in arg]
            if uargls:
                wfa.append([arg])
                if len(arg) > 2: arg = arg[1:-1]
                l = len(uargls)
                tag = [
                    list('{0:0>{1}}'.format(bin(i).split('b')[1], l))
                    for i in range(2**l)
                ]
                for it in tag:
                    uarg = ''
                    for i in range(l):
                        uarg += '*' + uargls[i][int(it[i])]
                    wfa[-1].append(arg + uarg)
        if wfa:
            for arg in wfa:
                args.remove(arg[0])
                args += [f'({it})' for it in arg[1:]]
        for i in range(len(args)):
            args[i] = '*'.join(
                sorted(args[i][1:-1].split('*'), key=lambda it: it[-1]))
        if self.test: print('fp_3: ', args)
        if wfa:
            return self.__sieveOut(f'({")+(".join(sorted(args))})', '+')
        else:
            return f'({")+(".join(sorted(args))})'

    def __partition(self, args, mode):
        bnum = 0
        pos = []
        for i in range(len(args)):
            if args[i] == '(':
                bnum += 1
            elif args[i] == ')':
                bnum -= 1
            elif args[i] == mode and not bnum:
                pos.append(i)
        t_ls = []
        if not pos: return t_ls
        pos = [-1] + pos + [len(args)]
        for i in range(1, len(pos)):
            t_ls.append(args[pos[i - 1] + 1:pos[i]])
        return t_ls

    def simplifiy(self, args):
        if len(args) < 3:
            return args
        elif '+' not in args:
            return self.__sieveOut(args, '*')
        args = self.__rEO(args, 1)
        if self.test: print('sy_1: ', args)
        args = self.downFalse(args)
        if self.test: print('sy_2: ', args)
        args = self.__sieveOut(args, '+')
        if self.test: print('sy_3: ', args)
        args = self.__distribute(args)
        if self.test: print('sy_4: ', args)
        return args

    def __sieveOut(self, args, mode):
        if self.test: print('st_1: ', args)
        ls = self.__partition(args, mode)
        if not ls: return args
        args = list(set(ls))
        if self.test: print('st_2: ', args)
        if mode == '+': return mode.join(args)
        uargs = [arg[1] for arg in args if arg[0] == '!']
        if self.test: print('st_3: ', args)
        if set(uargs) & set(args): return ''
        args = mode.join(args)
        if self.test: print('st_4: ', args)
        return args

    def downFalse(self, args):
        DfArgs = self.ptn[8].finditer(args)
        for DfArg in DfArgs:
            DfArg = DfArg.group()
            args = args.replace(DfArg, f'({self.__dCF(DfArg[2:-1],"*")})')
        return args

    def __dSF(self, args):
        #down simple false for main disjunctive paradigm|main conjunction paradigm
        if len(args) == 2:
            args = args[-1]
        elif len(args) == 1:
            args = '!' + args
        return args

    def __dCF(self, args, code):
        #down complex false for main disjunctive paradigm|main conjunction paradigm
        if code == '*': ucode = '+'
        else: ucode = '*'
        args = args.split(code)
        for i in range(len(args)):
            if len(args[i]) > 2:
                args[i] = f'({self.__dCF(args[i][1:-1], ucode)})'
            else:
                args[i] = self.__dSF(args[i])
        args = ucode.join(args)
        return args

    def __rSC(self, args):
        #remove single condition for main disjunctive paradigm|main conjunction paradigm
        if '-' in args:
            SgCdArgs = self.ptn[0].finditer(args)  #SingleConditionArguments
            for i, it in enumerate(SgCdArgs):
                it = it.group()
                pos = args.find(it)
                SgCdArgls = it.split('-')
                if '+' in SgCdArgls[0]:
                    SgCdArgls[0] = self.__dCF(SgCdArgls[0][1:-1], '+')
                elif '*' in SgCdArgls[0]:
                    SgCdArgls[0] = self.__dCF(SgCdArgls[0][1:-1], '*')
                else:
                    SgCdArgls[0] = self.__dSF(SgCdArgls[0])
                SgCdArgls[0] = self.__distribute(SgCdArgls[0])
                if len(SgCdArgls[0]) > 2: SgCdArgls[0] = f'({SgCdArgls[0]})'
                SgCdArgls = self.__rEO('+'.join(SgCdArgls), 1)
                args = args[:pos] + SgCdArgls + args[pos + len(it):]
        return args

    def __rDC(self, args):
        #remove double condition for main disjunctive paradigm|main conjunction paradigm
        if '=' in args:
            DbCdArgs = self.ptn[1].finditer(args)  #SingleConditionArguments
            for i, it in enumerate(DbCdArgs):
                it = it.group()
                pos = args.find(it)
                DbCdArgls = it.split('=')
                if self.test: print(f'rdc_1: ', DbCdArgls)
                t1 = self.__rEO(f'{DbCdArgls[0]}+{DbCdArgls[1]}', 1)
                if '+' in t1:
                    t1 = self.__dCF(t1, '+')
                elif '*' in t1:
                    t1 = self.__dCF(t1, '*')
                else:
                    t1 = self.__dSF(t1)
                t1 = self.__distribute(t1)
                t2 = self.__distribute(f'{DbCdArgls[0]}*{DbCdArgls[1]}')
                if t1 and t2:
                    t = self.__rEO(f'({t1})+({t2})', 1)
                else:
                    t = t1 + t2
                if t:
                    args = args[:pos] + t + args[pos + len(it):]
                else:
                    args = self.__rEO(
                        args[:pos - 1] + args[pos + len(it) + 1:], 3)
        return args

    def __rEO(self, args, *mode):
        #remove extra operator for main disjunctive paradigm|main conjunction paradigm
        def c(r, m):  #change re mode
            r = r.group()
            if r[0] == m:
                return m + r[2:-1]
            else:
                return r[1:-2] + m

        def rep1():  #+(a+b)
            nonlocal args
            args = self.ptn[2].sub(lambda r: c(r, '+'), args)
            args = self.__distribute(args)

        def rep2():  #*(a*b)
            nonlocal args
            args = self.ptn[3].sub(lambda r: c(r, '*'), args)

        def rep3():  #++ +... ...+
            nonlocal args
            args = re.sub(r'\+\+|\*\*', lambda r: r.group()[0], args)
            if args[0] in '+*':
                args = args[1:]
            elif args[-1] in '+*':
                args = args[:-1]

        for i in mode:
            eval(f'rep{i}()')
        return args

    def replace(self, args, arg):
        pos = args.find('%')
        if arg:
            if len(arg) > 2: arg = f'({arg})'
            return args[:pos] + arg + args[pos + 1:]
        else:
            return self.__rEO(args[:pos] + args[pos + 1:], 3)

    def __distribute(self, args):
        if len(args) < 5 or '+' not in args: return args
        DstrbtArgls = self.__partition(args, '*')
        if not DstrbtArgls: return args
        MDstrbtArgls = [arg for arg in DstrbtArgls if len(arg) > 2]
        if self.test: print('de1: ', MDstrbtArgls)
        SDstrbtArgls = '*'.join(list(set(DstrbtArgls) - set(MDstrbtArgls)))
        MDstrbtArgls = [arg[1:-1].split('+') for arg in MDstrbtArgls]
        for i in range(len(MDstrbtArgls)):
            for j in range(len(MDstrbtArgls[i])):
                if len(MDstrbtArgls[i][j]) > 2:
                    MDstrbtArgls[i][j] = MDstrbtArgls[i][j][1:-1]
        for i in range(1, len(MDstrbtArgls)):
            MDstrbtArgls[0] = [
                arg1 + '*' + arg2 for arg1 in MDstrbtArgls[0]
                for arg2 in MDstrbtArgls[i]
            ]
        if SDstrbtArgls:
            MDstrbtArgls = [
                self.__sieveOut(arg + '*' + SDstrbtArgls, '*')
                for arg in MDstrbtArgls[0]
            ]
        else:
            MDstrbtArgls = [
                self.__sieveOut(arg, '*') for arg in MDstrbtArgls[0]
            ]
        if self.test: print('de2: ', MDstrbtArgls)
        MDstrbtArgls = [arg for arg in MDstrbtArgls if arg]
        if MDstrbtArgls:
            return '(' + ')+('.join(MDstrbtArgls) + ')'
        else:
            return ''


class argument:

    def __init__(self, item=None) -> None:
        self.item = item
        self.branch = []

    def setItem(self, item):
        self.item = item

    def __str__(self) -> str:

        def traverse(node):
            s = node.item[:]
            for arg in node.branch:
                if arg.branch:
                    t = traverse(arg)
                else:
                    t = arg.item
                pos = s.find('%')
                if len(t) > 2: t = f'({t})'
                s = s[:pos] + t + s[pos + 1:]
            return s

        return traverse(self)


class argumentTree:

    def __init__(self, root, how=True, test=False) -> None:
        self.root = root
        self.ttp = trueTableProcess(how, test)
        self.args = self.ttp.judge(root)
        if not self.args: 
            print('表达式错误')
            self.judge=True
            return
        else:self.judge=False
        self.__setTree()

    def __str__(self) -> str:

        def traverse(node):
            s = node.item[:]
            for arg in node.branch:
                if arg.branch:
                    t = traverse(arg)
                else:
                    t = arg.item
                pos = s.find('%')
                if len(t) > 2: t = f'({t})'
                s = s[:pos] + t + s[pos + 1:]
            return s

        return traverse(self.root)

    def getStr(self):
        return self.__str__()

    def __setTree(self):
        def set(args):
            if '(' not in args: return argument(args)
            arg = argument()
            pos = []
            bnum = 0
            for i in range(len(args)):
                if args[i] == '(':
                    if pos:
                        bnum += 1
                    else:
                        pos.append(i)
                elif args[i] == ')':
                    if bnum: bnum -= 1
                    else:
                        pos[-1] = (pos[-1], i)
                        arg.branch.append(set(args[pos[-1][0] + 1:pos[-1][1]]))
            for p in pos[::-1]:
                args = args[0:p[0]] + '%' + args[p[1] + 1:]
            arg.setItem(args)
            return arg

        self.root = set(self.root)

    def process(self):
        if self.judge:return
        def traverse(node):
            for b in node.branch:
                if b.branch:
                    traverse(b)
                else:
                    b.branch.clear()
                    self.ttp.process(self, b)
                node.setItem(self.ttp.replace(node.item, b.item))
            node.branch.clear()
            self.ttp.process(self, node)
        traverse(self.root)
        self.root.setItem(self.ttp.finPar(self.root.item, self.args))
        self.printTrueTable()

    def printTrueTable(self):
        print(' '.join(self.args), self.root.item)
        t_l = len(self.args)
        for i in range(2**t_l):
            t_ls = list('{0:0>{1}}'.format(bin(i).split('b')[1], t_l))
            print(' '.join(t_ls), end=' ')
            t_s = self.root.item[:]
            for j in range(t_l):
                # print(t_ls[j],int(t_ls[j]),not ord(t_ls[j]),int(not ord(t_ls[j])),str(int(not ord(t_ls[j]))))
                t_s = t_s.replace('!' + self.args[j],str(int(not int(t_ls[j]))))\
                         .replace(self.args[j], t_ls[j])
            print('{0: >{1}}'.format(eval(t_s), 10))


# (a-!c)*((a*!b)+(b*!a))*(c=d)*(c-e)*(e-(a+b+d))
# (w-!l)*((w*!c)+(c*!w))*(c=l)*(y-c)
if __name__ == '__main__':
    print('析取:+合取:*单条件:-双条件:=')
    msg=eval(input('是否需要过程(1|0):'))
    while True:
        args = input()
        args = argumentTree(args,msg)
        args.process()
    # print([arg.group() for arg in ptn.finditer(args)])
    # print([arg.group() for arg in trueTableProcess.ptn[8].finditer(args)])
    # print(trueTableProcess.ptn[7].match(args).group())
    #提取主析取范式